const { app, BrowserWindow, ipcMain, dialog } = require('electron');
const path = require('path');
const fs = require('fs');
const fs_promises = fs.promises;
const os = require('os');
const ExifParser = require('exif-parser');
const { shell } = require('electron');

const home_path = os.homedir();
const cache_path = path.join(home_path, '.spidermap');
if (!fs.existsSync(cache_path)) {
  fs.mkdirSync(cache_path);  
}

const current_path_cfg = path.join(cache_path, 'current_path.cfg');
const user_data_path = path.join(cache_path, 'userdata.json');
const visible_track_path = path.join(cache_path, 'visible-tracks.json');
const map_config_path = path.join(cache_path, 'mapconfig.json');
const track_data_path = path.join(cache_path, 'trackdata');
if (!fs.existsSync(track_data_path)) {
  fs.mkdirSync(track_data_path);  
}

let current_file_path;
try {
  current_file_path = fs.readFileSync(current_path_cfg, 'utf8');
} catch (err) {
  current_file_path = home_path;
}

let main_window;


function createWindow() {
  main_window = new BrowserWindow({
    width: 1680,
    height: 1050,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: false,
      contextIsolation: true,
      webSecurity: true
    },
    icon: path.join(__dirname, 'assets/icons/app-icon.png')
  });

  if (process.platform === 'win32') {
    main_window.maximize();
  }

  main_window.setMenu(null);
  main_window.loadFile('webapp/www/index.html');

  // *************打包发行版时注释掉*****************
  // main_window.webContents.openDevTools();

  // 监听用户点击close，覆盖原有动作
  main_window.on('close', (event) => {
    event.preventDefault(); // 阻止窗口立即关闭
    // 保存当前打开/保存文件路径
    fs.writeFileSync(current_path_cfg, current_file_path);
    // 提交渲染进程存档其他应用数据
    main_window.webContents.send('ready_to_quit');
  });

  main_window.on('closed', () => {
    main_window = null;
  });
}

app.whenReady().then(() => {
  createWindow();

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});


/************************************************************************** */
// 跨进程通信
/************************************************************************** */
// 打开文件对话框，选择打开轨迹文件
ipcMain.handle('open-track-file', async (event) => {
  const selected_files = await dialog.showOpenDialog(main_window, {
    defaultPath: current_file_path,
    filters: [
      { name: '轨迹文件', extensions: ['kml', 'gpx'] },
      { name: 'KML文件', extensions: ['kml'] },
      { name: 'GPX文件', extensions: ['gpx'] },
      { name: '所有文件', extensions: ['*'] }
    ],
    properties: ['openFile', 'multiSelections'],
  });

  if (selected_files.canceled  || selected_files.filePaths.length < 1) {
    return { canceled: true };
  }

  current_file_path = path.dirname(selected_files.filePaths[0]);

  const track_files = [];
  let error = '读取文件失败';

  for (const file_path of selected_files.filePaths) {
    try {
      const file_content = await fs_promises.readFile(file_path, 'utf8');
      track_files.push({
        file_name: path.basename(file_path),
        file_content,
      });
    } catch (err) {
        error = err.message;
    }
  }
    
  if (track_files.length > 0) {
    return { track_files };
  } else {
    return { error };
  }

});

// 备份用户数据
ipcMain.on('save-user-data', async (event, data) => {
  await fs_promises.writeFile(user_data_path, data);  // 不返回结果时前边可以不写await
});

// 备份轨迹数据
ipcMain.on('save-track-data', async (event, data) => {
  const track_path = path.join(track_data_path, data.track_uuid + '.tps')
  await fs_promises.writeFile(track_path, data.track_data);
});

// 删除轨迹数据
ipcMain.on('delete-track-data', async (event, track_uuid) => {
  const track_path = path.join(track_data_path, track_uuid + '.tps')
  await fs_promises.unlink(track_path);
});

// 按需加载轨迹数据
ipcMain.handle('load-track-data', async (event, track_uuid) => {
  try {
    const track_path = path.join(track_data_path, track_uuid + '.tps')
    const track_data = await fs_promises.readFile(track_path, 'utf8');
    return JSON.parse(track_data);
  } catch (err) {
    return null;
  }
});

// 退出时备份配置数据
ipcMain.on('save-snapshot', async (event, data) => {
  const snapshot = JSON.parse(data);
  
  const user_data = snapshot.user_data;
  await fs_promises.writeFile(user_data_path, user_data);

  const map_config = snapshot.map_config;
  await fs_promises.writeFile(map_config_path, map_config);

  const visible_track_uuids = snapshot.visible_track_uuids;
  await fs_promises.writeFile(visible_track_path, visible_track_uuids);

  // 备份完数据后再关闭渲染窗口
  main_window.destroy();
});

// 启动时加载用户数据
ipcMain.handle('load-user-data', async () => {
  try {
    const user_data = await fs_promises.readFile(user_data_path, 'utf8');
    return JSON.parse(user_data);
  } catch (err) {
    return null;
  }
});

// 启动时加载可视轨迹数据
ipcMain.handle('load-visible-tracks', async () => {
  try {
    const visible_tracks = await fs_promises.readFile(visible_track_path, 'utf8');
    return JSON.parse(visible_tracks);
  } catch (err) {
    return [];
  }
});


// 启动时加载地图配置数据
ipcMain.handle('load-map-config', async () => {
  try {
    const map_config = await fs_promises.readFile(map_config_path, 'utf8');
    return JSON.parse(map_config);
  } catch (err) {
    return null;
  }
});


// 打开文件保存对话框，选择保存轨迹文件
ipcMain.handle('save-track-file', async (event, data) => {
  const {filename, file_content} = data;

  const result = await dialog.showSaveDialog(main_window, {
    defaultPath: path.join(current_file_path, filename),
    filters: [
      { name: 'KML文件', extensions: ['kml'] },
    ],
  });

  if (!result.canceled && !!result.filePath) {
    current_file_path = path.dirname(result.filePath);
    try {
        await fs_promises.writeFile(result.filePath, file_content);
        return { path: result.filePath };
    } catch (err) {
        return { error: err.message };
    }
  }

  return { canceled: true };
});


// 访问天地图
ipcMain.handle('get-tianditu-route', async (event, url) => {
  try {
    const response = await fetch(url);
    let text = await response.text();

    const route = [];
    while (text.indexOf('<streetLatLon>') >= 0) {
      const start = text.indexOf('<streetLatLon>') + 14;
      const end = text.indexOf('</streetLatLon>') - 1;  // 最后一个坐标后面有一个分号（;）,所以需要减一

      const points = text.substring(start, end).split(';')
      for (let point of points) {
        const tmp = point.split(',');
        route.push({ lon: parseFloat(tmp[0]), lat: parseFloat(tmp[1]) });
      }

      text = text.substring(end + 1 + 15);
    }

    return route;
  } catch (err) {
    return [];
  }

});

// 打开文件对话框，选择打开照片文件
ipcMain.handle('open-photo-file', async (event) => {
  const result = await dialog.showOpenDialog(main_window, {
    defaultPath: current_file_path,
    filters: [
      { name: '照片文件', extensions: ['jpg', 'png', 'jpeg'] }
    ],
    properties: ['openFile'],
  });

  if (!result.canceled && result.filePaths.length > 0) {
    const file_path = result.filePaths[0];
    current_file_path = path.dirname(file_path);
    try {
        const fileContent = await fs_promises.readFile(file_path);

        const parser = ExifParser.create(fileContent);
        const exif = parser.parse();
        const tags = exif.tags

        if (!tags.GPSLongitude || !tags.GPSLatitude) {
          return { error: '该照片无经纬度坐标信息！' };
        }

        const format = file_path.endsWith('png') ? 'png' : 'jpeg';
        const url = `data:image/${format};base64,` + fileContent.toString('base64');

        const photo = {
          label: path.basename(file_path),
          url,
          type: 'photo',
        }

        if (!!tags) {
            photo.height = tags.ExifImageHeight || null;
            photo.width = tags.ExifImageWidth || null;

            photo.lon = tags.GPSLongitude || null;
            if (!!photo.lon && tags.GPSLongitudeRef === 'W') {
              photo.lon = 0 - photo.lon;
            }
            photo.lat = tags.GPSLatitude || null;
            if (!!photo.lat && tags.GPSLatitudeRef === 'S') {
              photo.lat = 0 - photo.lat;
            }
            photo.alt = tags.GPSAltitude || null;

            photo.timestamp = tags.GPSDateStamp || null;
            if (!!photo.timestamp) {
              photo.timestamp = photo.timestamp.replace(/:/g, '-');
              photo.timestamp += `T${tags.GPSTimeStamp[0].toFixed(0).padStart(2, 0)}:${tags.GPSTimeStamp[1].toFixed(0).padStart(2, 0)}:${tags.GPSTimeStamp[2].toFixed(0).padStart(2, 0)}Z`;
            }
            
            photo.direction = tags.GPSImgDirection || null;
        }

        return photo;
    } catch (err) {
        return { error: err.message };
    }
  }

  return { canceled: true };
});

// 打开文件保存对话框，选择保存图像文件
ipcMain.handle('save-map-screenshot', async (event, data) => {
  const {filename, img_url} = data;
  const buffer = Buffer.from(img_url.substring('data:image/png;base64,'.length), 'base64');

  const result = await dialog.showSaveDialog(main_window, {
    defaultPath: path.join(current_file_path, filename),
    filters: [
      { name: '图像文件', extensions: ['png'] },
    ],
  });

  if (!result.canceled && !!result.filePath) {
    current_file_path = path.dirname(result.filePath);
    try {
        await fs_promises.writeFile(result.filePath, buffer);
        return { path: result.filePath };
    } catch (err) {
        return { error: err.message };
    }
  }

  return { canceled: true };
});

// 打开DevTools
ipcMain.on('open-dev-tools', async (event) => {
  main_window.webContents.openDevTools();
});

// 打开开源主页
ipcMain.on('open-source-homepage', async (event) => {
  shell.openExternal('http://gitee.com/huolongshe/spider-map');
});
